package io.github.lee.core.ui

import android.content.Context
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import android.widget.Toast
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.widget.Toolbar
import androidx.core.view.WindowCompat
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import io.github.lee.core.ui.databinding.UiBaseHoverBinding
import io.github.lee.core.ui.databinding.UiBaseLinearBinding
import io.github.lee.core.ui.databinding.UiLayoutProgerssBinding
import io.github.lee.core.util.toPx
import io.github.lee.core.vm.BaseViewModel
import io.github.lee.core.vm.data.UiEvent
import io.github.lee.core.vm.data.UiState
import io.github.lee.core.vm.err.ViewModelException
import razerdp.basepopup.BasePopupWindow


open class BaseActivity<VB : ViewDataBinding, VM : BaseViewModel> : AppCompatActivity() {
    protected val mContext: Context by lazy { this }
    protected open var isHover = false

    //        protected val vm: VM? by  { viewM }
    protected var vm: VM? = null

    protected lateinit var toolbarFrameLayout: FrameLayout
        private set
    protected lateinit var contentFrameLayout: FrameLayout
        private set

    protected val toolbar: Toolbar? by lazy { onCreateToolbar() }
    protected val loadingVb: ViewDataBinding? by lazy { onCreateLoading() }
    protected val vb: VB? by lazy { onCreateSuccess() }
    protected val emptyVb: ViewDataBinding? by lazy { onCreateEmpty() }
    protected val errorVb: ViewDataBinding? by lazy { onCreateError() }

    //===Desc:======================================================================================
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        onInitData(savedInstanceState)
        if (isFinishing) return

        vm = onCreateViewModel()?.value?.also { lifecycle.addObserver(it) }

        //加载布局
        val root = if (isHover) {
            val v = UiBaseHoverBinding.inflate(layoutInflater)
            toolbarFrameLayout = v.flToolbarRoot
            contentFrameLayout = v.flContentRoot
            v
        } else {
            val v = UiBaseLinearBinding.inflate(layoutInflater)
            toolbarFrameLayout = v.flToolbarRoot
            contentFrameLayout = v.flContentRoot
            v
        }

        //加载子类布局
        if (null != toolbar) {
            toolbarFrameLayout.removeAllViews()
            toolbarFrameLayout.addView(toolbar)
            toolbar?.title = ""
            setSupportActionBar(toolbar)
            toolbarFrameLayout.visibility = View.VISIBLE
        } else {
            toolbarFrameLayout.visibility = View.GONE
        }

        loadingVb?.also {
            it.lifecycleOwner = this@BaseActivity
            contentFrameLayout.addView(it.root)
        }
        vb?.also {
            it.lifecycleOwner = this@BaseActivity
            contentFrameLayout.addView(it.root)
        }
        emptyVb?.also {
            it.lifecycleOwner = this@BaseActivity
            contentFrameLayout.addView(it.root)
        }
        errorVb?.also {
            it.lifecycleOwner = this@BaseActivity
            contentFrameLayout.addView(it.root)
        }
        setContentView(root.root)

        onObserved()
        onSetViewListener()

        //判断状态显示
        if (null != loadingVb) {
            if (null == vm) {
                showLoading()
            } else {
                vm?.emitUiState(UiState.Loading())
            }
        } else {
            if (null != vb) {
                if (null == vm) {
                    showSuccess()
                } else {
                    vm?.emitUiState(UiState.Success)
                }
            } else {
                if (null != emptyVb) {
                    if (null == vm) {
                        showEmpty()
                    } else {
                        vm?.emitUiState(UiState.Empty())
                    }
                } else {
                    if (null != errorVb) {
                        if (null == vm) {
                            showError()
                        } else {
                            vm?.emitUiState(UiState.Error())
                        }
                    } else {//子类没有实现任何布局，隐藏
                        contentFrameLayout.visibility = View.INVISIBLE
                    }
                }
            }
        }
        onSetViewData()
    }

    override fun onDestroy() {
        super.onDestroy()
        if (null != vm) {
            lifecycle.removeObserver(vm!!)
        }
        loadingVb?.apply { lifecycleOwner = null }
        vb?.apply { lifecycleOwner = null }
        emptyVb?.apply { lifecycleOwner = null }
        errorVb?.apply { lifecycleOwner = null }
    }

    //===Desc:======================================================================================
    protected open fun onCreateViewModel(): Lazy<VM>? = null

    protected open fun onCreateToolbar(): Toolbar? = null
    protected open fun onCreateLoading(): ViewDataBinding? = null
    protected open fun onCreateSuccess(): VB? = null
    protected open fun onCreateEmpty(): ViewDataBinding? = null
    protected open fun onCreateError(): ViewDataBinding? = null

    //===Desc:======================================================================================

    protected open fun onInitData(savedInstanceState: Bundle?) {}

    protected open fun onObserved() {
        vm?.apply {
            collectUiState {
                when (it) {
                    UiState.None -> showLoading()
                    is UiState.Loading -> showLoading(it.tip)
                    UiState.Success -> showSuccess()
                    is UiState.Empty -> showEmpty(it.t)
                    is UiState.Error -> showError(it.t)
                }
            }
            collectUiEvent {
                when (it) {
                    UiEvent.None -> {}
                    is UiEvent.ShowProgress -> this@BaseActivity.showProgress(it.tip, it.canDismiss)
                    is UiEvent.HideProgress -> this@BaseActivity.hideProgress(it.runnable)
                    is UiEvent.Toast -> this@BaseActivity.toast(it.msg, it.isLong)

                    is UiEvent.RefreshSuccess -> this@BaseActivity.refreshSuccess(it.hasMore)
                    is UiEvent.RefreshFail -> this@BaseActivity.refreshFail(it.e)
                    is UiEvent.LoadMoreSuccess -> this@BaseActivity.loadMoreSuccess(it.hasMore)
                    is UiEvent.LoadMoreFail -> this@BaseActivity.loadMoreFail(it.e)
                }
            }

            collectSoftKeyboard {
                if (it) {
                    //显示键盘
                } else {
                    // hide
                    io.github.lee.core.util.hideSoftKeyboard(window.decorView)
                }
            }
        }

    }

    protected open fun onSetViewListener() {}
    protected open fun onSetViewData() {}

    //===Desc:======================================================================================

    protected open fun showLoading(tip: String? = "") {
        loadingVb?.root?.visibility = View.VISIBLE
        vb?.root?.visibility = View.GONE
        emptyVb?.root?.visibility = View.GONE
        errorVb?.root?.visibility = View.GONE
    }

    protected open fun showSuccess() {
        loadingVb?.root?.visibility = View.GONE
        vb?.root?.visibility = View.VISIBLE
        emptyVb?.root?.visibility = View.GONE
        errorVb?.root?.visibility = View.GONE
    }

    protected open fun showEmpty(e: ViewModelException? = null) {
        loadingVb?.root?.visibility = View.GONE
        vb?.root?.visibility = View.GONE
        emptyVb?.root?.visibility = View.VISIBLE
        errorVb?.root?.visibility = View.GONE
    }

    protected open fun showError(e: ViewModelException? = null) {
        loadingVb?.root?.visibility = View.GONE
        vb?.root?.visibility = View.GONE
        emptyVb?.root?.visibility = View.GONE
        errorVb?.root?.visibility = View.VISIBLE
    }

    class ProgressPopupWindow(context: Context?) : BasePopupWindow(context) {
        val vb = UiLayoutProgerssBinding.inflate(LayoutInflater.from(context))

        init {
            contentView = vb.root
            width = 100.toPx(getContext())
            height = 100.toPx(getContext())
        }


        fun setTip(tip: String?) {
            vb.tip = tip
        }
    }

    private val progress by lazy {
        ProgressPopupWindow(this)
    }

    protected open fun showProgress(tip: String? = null, canDismiss: Boolean? = true) {
        progress.setTip(tip)
        if (!progress.isShowing) {
            progress.setBackgroundColor(Color.TRANSPARENT)
            progress.popupGravity = Gravity.CENTER
            progress.setOutSideDismiss(canDismiss ?: true)
            progress.showPopupWindow()
        }
    }

    protected open fun hideProgress(runnable: Runnable? = null) {
        if (progress.isShowing) {
            progress.dismiss()
        }
    }


    protected open fun toast(msg: String? = null, isLong: Boolean = false) {
        if (msg.isNullOrEmpty()) {
            return
        }
        Toast.makeText(mContext, msg, if (isLong) Toast.LENGTH_LONG else Toast.LENGTH_SHORT)
            .show()
    }
    protected open fun toast(@StringRes resId: Int?, isLong: Boolean = false) {
        if (null == resId) {
            return
        }
        toast(getString(resId), isLong)
    }

    protected open fun refreshSuccess(hasMore: Boolean? = true) {

    }

    protected open fun refreshFail(e: ViewModelException? = null) {

    }

    protected open fun loadMoreSuccess(hasMore: Boolean? = true) {

    }

    protected open fun loadMoreFail(e: ViewModelException? = null) {

    }


    //===Desc:======================================================================================
    protected fun statusBarColor(
        @ColorInt color: Int,
        isDark: Boolean = false,
        fitsSystem: Boolean = true
    ) {
        WindowCompat.setDecorFitsSystemWindows(window, fitsSystem)
        window.statusBarColor = color
        WindowCompat.getInsetsController(window, window.decorView)
            .isAppearanceLightStatusBars = isDark
    }

    protected fun navigationBarColor(
        @ColorInt color: Int,
        isDark: Boolean = false
    ) {
        window.navigationBarColor = color
        WindowCompat.getInsetsController(window, window.decorView)
            .isAppearanceLightNavigationBars = !isDark
    }

    protected fun setNavigationIcon(
        @DrawableRes resId: Int,
        listener: View.OnClickListener? = null
    ) {
        toolbar?.setNavigationIcon(resId)
        toolbar?.setNavigationOnClickListener(listener)
    }

    protected fun setNavigationIcon(
        @DrawableRes resId: Int,
        @ColorInt tintColor: Int? = null,
        listener: View.OnClickListener? = null
    ) {
        if (null == tintColor) {
            toolbar?.setNavigationIcon(resId)
            toolbar?.setNavigationOnClickListener(listener)
        } else {
            val drawable = AppCompatResources.getDrawable(mContext, resId)
            setNavigationIcon(drawable, tintColor, listener)
        }
    }

    protected fun setNavigationIcon(
        drawable: Drawable?,
        @ColorInt tintColor: Int? = null,
        listener: View.OnClickListener? = null
    ) {
        if (null != tintColor) {
            drawable?.setTint(tintColor)
        }
        toolbar?.navigationIcon = drawable
        toolbar?.setNavigationOnClickListener(listener)
    }

    protected fun replaceFragment(f: Fragment) {
        supportFragmentManager
            .beginTransaction()
            .replace(contentFrameLayout.id, f)
            .commitNowAllowingStateLoss()
        contentFrameLayout.visibility = View.VISIBLE
    }

}


